//
//  ExScanQRCodeViewController.m
//  OC-Example
//
//  Created by apang on 2018/8/3.
//  Copyright © 2018年 apang.men All rights reserved.
//

#import "ExScanQRCodeViewController.h"
#import <AVFoundation/AVFoundation.h>

#define scanWidth SCREEN_BOUNDS.width * (225.0/375.0)

#define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
#define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)

@interface ScanQRcodeContainerView : UIView
{
    CGFloat x;
    CGFloat y;
    CGFloat lineLength;
    CGFloat lineWidth;
    UIColor * cornerColor;
}
@property(nonatomic, strong) UIImageView * lineImageView;
@end
@implementation ScanQRcodeContainerView
- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setBackgroundColor:[UIColor clearColor]];
        x = (SCREEN_WIDTH-scanWidth)/2.0;
        y = (SCREEN_HEIGHT-scanWidth)/2.0;
        lineLength = 24.0;//注意修改
        lineWidth = 2.0;
        cornerColor = [UIColor colorWithRed:37.0033/255.0 green:99.0024/255.0 blue:239.996/255.0 alpha:1];
        _lineImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"centerLine"]];
        CGFloat imageW = scanWidth-20.0;
        CGFloat imageH = imageW/(449.0/8.0);
        [_lineImageView setFrame:CGRectMake(x, y, imageW, imageH)];//449/8
        [self addSubview:_lineImageView];
        [self scanAnimation];
    }
    return self;
}

- (void)leftTopCorner {
    UIBezierPath * bezierPath = [UIBezierPath bezierPath];
    bezierPath.lineWidth = lineWidth;
    CGFloat midGap = lineWidth/2.0;//中线
    [bezierPath moveToPoint:CGPointMake(x+lineLength-midGap, y-midGap)];//最右点;
    [bezierPath addLineToPoint:CGPointMake(x-midGap, y-midGap)];//左边最顶点
    [bezierPath addLineToPoint:CGPointMake(x-midGap, y+lineLength)];//左顶下;
    [cornerColor set];
    [bezierPath stroke];
}

- (void)rightTopCorner {
    UIBezierPath * bezierPath = [UIBezierPath bezierPath];
    bezierPath.lineWidth = lineWidth;
    CGFloat midGap = lineWidth/2.0;//中线
    [bezierPath moveToPoint:CGPointMake(x+scanWidth-lineLength+midGap, y-midGap)];//最左点;
    [bezierPath addLineToPoint:CGPointMake(x+scanWidth+midGap, y-midGap)];//右边边最顶点
    [bezierPath addLineToPoint:CGPointMake(x+scanWidth+midGap, y+lineLength)];//右顶下;
    [cornerColor set];
    [bezierPath stroke];
}

- (void)rightBottomCorner {
    UIBezierPath * bezierPath = [UIBezierPath bezierPath];
    bezierPath.lineWidth = lineWidth;
    CGFloat midGap = lineWidth/2.0;//中线
    [bezierPath moveToPoint:CGPointMake(x+scanWidth+midGap, y+scanWidth-lineLength+midGap)];//右下最高点;
    [bezierPath addLineToPoint:CGPointMake(x+scanWidth+midGap, y+scanWidth+midGap)];//右下最低点
    [bezierPath addLineToPoint:CGPointMake(x+scanWidth-lineLength+midGap, y+scanWidth+midGap)];//右下最左点;
    [cornerColor set];
    [bezierPath stroke];
}

- (void)leftBottomCorner {
    UIBezierPath * bezierPath = [UIBezierPath bezierPath];
    bezierPath.lineWidth = lineWidth;
    CGFloat midGap = lineWidth/2.0;//中线
    [bezierPath moveToPoint:CGPointMake(x-midGap, y+scanWidth-lineLength+midGap)];//左上;
    [bezierPath addLineToPoint:CGPointMake(x-midGap, y+scanWidth+midGap)];//左边最低点
    [bezierPath addLineToPoint:CGPointMake(x+lineLength-midGap, y+scanWidth+midGap)];//最右点;
    [cornerColor set];
    [bezierPath stroke];
}

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    /// 空白区域设置
    [[[UIColor blackColor] colorWithAlphaComponent:0.6] setFill];
    UIRectFill(rect);
    // 获取上下文，并设置混合模式 -> kCGBlendModeDestinationOut
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetBlendMode(context, kCGBlendModeDestinationOut);
    // 设置空白区
    UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:CGRectMake(x, y, scanWidth, scanWidth)];
    [bezierPath fill];
    // 执行混合模式
    CGContextSetBlendMode(context, kCGBlendModeNormal);
    [self leftTopCorner];
    [self rightTopCorner];
    [self rightBottomCorner];
    [self leftBottomCorner];
}

- (void)scanAnimation {
    
    [UIView beginAnimations:@"animationID" context:NULL];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(scanAnimationStop)];
    [UIView setAnimationDuration:4];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.lineImageView cache:YES];
    [UIView setAnimationRepeatCount:150];
    CGRect origin = self.lineImageView.frame;
    origin.origin.y = y+scanWidth-2.0*origin.size.height;
    [self.lineImageView setFrame:origin];
    [UIView commitAnimations];
}

- (void)scanAnimationStop {
    if (self.lineImageView) {
        CGRect origin = self.lineImageView.frame;
            origin.origin.y = y + (scanWidth-origin.size.height)/2.0;
        [self.lineImageView setFrame:origin];
    }
    [_lineImageView.layer removeAllAnimations];
}

@end

@interface ExScanQRCodeViewController ()<AVCaptureMetadataOutputObjectsDelegate>
{
    CGRect scanContainerRect;
}
@property (nonatomic, strong) AVCaptureDevice * captureDevice;
@property (nonatomic, strong) AVCaptureDeviceInput * deviceInput;
@property (nonatomic, strong) AVCaptureMetadataOutput * metaDataOutput;
@property (nonatomic, strong) AVCaptureSession * captureSession;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer * videoPreviewLayer;

@property (nonatomic, strong) ScanQRcodeContainerView * backView;
/*** 专门用于保存描边的图层 ***/
@property (nonatomic,strong) CALayer *containerLayer;
@end

@implementation ExScanQRCodeViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self.view setBackgroundColor:[UIColor whiteColor]];
    self.extendedLayoutIncludesOpaqueBars = YES;//穿透
    self.title = @"扫描二维码";
    scanContainerRect = CGRectMake((SCREEN_WIDTH-scanWidth)/2.0, (SCREEN_HEIGHT-scanWidth)/2.0, scanWidth, scanWidth);
    _backView = [[ScanQRcodeContainerView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
    [self.view addSubview:_backView];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
//    [self.navigationController setNavigationBarHidden:YES animated:YES];
    [self startScan];
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

#pragma mark AVCaptureMetadataOutput's Delegate

- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
    
    AVMetadataMachineReadableCodeObject *object = [metadataObjects lastObject];
    
    if (object == nil){
        if (self.containerLayer.sublayers)
        {
            for (CALayer *subLayer in self.containerLayer.sublayers)
            {
                [subLayer removeFromSuperlayer];
            }
        }
    }else{
        NSLog(@"%@",object.stringValue);
        [self.captureSession stopRunning];
        [_backView scanAnimationStop];
        AVMetadataMachineReadableCodeObject *obj = (AVMetadataMachineReadableCodeObject *)[self.videoPreviewLayer transformedMetadataObjectForMetadataObject:object];
        [self drawLine:obj];
    }
}

- (void)startScan {
    __block BOOL author = YES;
    if (![AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) {
        author = NO;
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
            author = granted;
        }];
    }
    if (author) {
        if (!_captureSession) {
            if (![self.captureSession canAddInput:self.deviceInput]) return;
            [self.captureSession addInput:self.deviceInput];
            if (![self.captureSession canAddOutput:self.metaDataOutput]) return;
            [self.captureSession addOutput:self.metaDataOutput];
            
            self.metaDataOutput.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];//指定类型为二维码
            [self.metaDataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
            
            [self.view.layer insertSublayer:self.videoPreviewLayer atIndex:0];
            self.videoPreviewLayer.frame = self.view.frame;
            
            [self.view.layer addSublayer:self.containerLayer];
            self.containerLayer.frame = self.view.bounds;
        }
        
        [self.captureSession startRunning];
    }
}

// 绘制描边
- (void)drawLine:(AVMetadataMachineReadableCodeObject *)objc
{
    NSArray *array = objc.corners;
    
    // 1.创建形状图层, 用于保存绘制的矩形
    CAShapeLayer *layer = [[CAShapeLayer alloc] init];
    
    // 设置线宽
    layer.lineWidth = 2;
    layer.strokeColor = [UIColor greenColor].CGColor;
    layer.fillColor = [UIColor clearColor].CGColor;
    
    // 2.创建UIBezierPath, 绘制矩形
    UIBezierPath *path = [[UIBezierPath alloc] init];
    CGPoint point = CGPointZero;
    int index = 0;
    
    CFDictionaryRef dict = (__bridge CFDictionaryRef)(array[index++]);
    // 把点转换为不可变字典
    // 把字典转换为点，存在point里，成功返回true 其他false
    CGPointMakeWithDictionaryRepresentation(dict, &point);
    
    [path moveToPoint:point];
    
    // 2.2连接其它线段
    for (int i = 1; i<array.count; i++) {
        CGPointMakeWithDictionaryRepresentation((__bridge CFDictionaryRef)array[i], &point);
        [path addLineToPoint:point];
    }
    // 2.3关闭路径
    [path closePath];
    
    layer.path = path.CGPath;
    // 3.将用于保存矩形的图层添加到界面上
    [self.containerLayer addSublayer:layer];
    
}



#pragma mark getter
- (AVCaptureDevice *)captureDevice {
    if (!_captureDevice) {
        _captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//        if (_captureDevice.isFocusPointOfInterestSupported && _captureDevice.isAutoFocusRangeRestrictionSupported) {
//            NSError *error;
//            [_captureDevice lockForConfiguration:&error];
//            [_captureDevice setFocusPointOfInterest:CGPointMake(0.2, 0.2)];
//            [_captureDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
//            [_captureDevice unlockForConfiguration];
//        }
    }
    return _captureDevice;
}

- (AVCaptureDeviceInput *)deviceInput {
    if (!_deviceInput) {
        _deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:self.captureDevice error:nil];
    }
    return _deviceInput;
}

- (AVCaptureMetadataOutput *)metaDataOutput {
    if (!_metaDataOutput) {
        _metaDataOutput = [[AVCaptureMetadataOutput alloc] init];
        //MARK:设置可解析元数据范围 ，坐标系是鬼啊 我们常用的坐标系应该处于第四象限，这个元数的采取范围坐标系 使我们原来坐标系 顺时针旋转90º 在水平翻转后的结果
        _metaDataOutput.rectOfInterest = CGRectMake(CGRectGetMinY(scanContainerRect)/SCREEN_HEIGHT,CGRectGetMinX(scanContainerRect)/SCREEN_WIDTH, scanWidth/SCREEN_HEIGHT,scanWidth/SCREEN_WIDTH);
    }
    return _metaDataOutput;
}

- (AVCaptureSession *)captureSession {
    if (!_captureSession) {
        _captureSession = [[AVCaptureSession alloc] init];
    }
    return _captureSession;
}

- (AVCaptureVideoPreviewLayer *)videoPreviewLayer {
    if (!_videoPreviewLayer) {
        _videoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
        _videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    }
    return _videoPreviewLayer;
}

- (CALayer *)containerLayer
{
    if (_containerLayer == nil) {
        _containerLayer = [[CALayer alloc] init];
    }
    return _containerLayer;
}
@end
